﻿using BCCommon;
using BCCommon.TMS.MarketingCoupon;
using BCData.TMS.MarketingCoupon.MarketingCoupon;
using BCData.TMS.MarketingCoupon.MarketingCouponReceive;
using BCData.TMS.MarketingCoupon.MarketingCouponType;
using BCData.TMS.MarketingCoupon.MarketingCouponUsing;
using BCData.TMS.Order.Order;
using BCDto.Sim.Admin.Admin;
using BCDto.TMS.MarketingCoupon.MarketingCoupon;
using BCDto.TMS.MarketingCoupon.MarketingCouponType;
using BCDto.Website.User;
using BCEntity.Common.EntityNameConst;
using BCEntity.TMS.MarketingCoupon.MarketingCoupon;
using BCEntity.TMS.MarketingCoupon.MarketingCouponReceive;
using BCEntity.TMS.MarketingCoupon.MarketingCouponUsing;
using BCService.Common.Area;
using BCService.TMS.Agent.AgentAreaRecord;
using BCService.Utils;
using System;
using System.Collections.Generic;

namespace BCService.TMS.MarketingCoupon.MarketingCoupon
{
    public class MarketingCouponService : IMarketingCouponService
    {
        private readonly IMarketingCouponTypeData marketingCouponTypeData;
        private readonly IDatabaseContext databaseContext;
        private readonly IMarketingCouponData marketingCouponData;
        private readonly IRedisService redisService;
        private readonly IAgentAreaRecordService agentAreaRecordService;
        private readonly IZoneService zoneService;
        private readonly IMarketingCouponReceiveData marketingCouponReceiveData;
        private readonly IMarketingCouponUsingData marketingCouponUsingData;
        private readonly IOrderData orderData;
        private readonly string key = string.Format("{0}", EntityNameConst.MarketingCouponEntity);
        private readonly string keyType = string.Format("{0}", EntityNameConst.MarketingCouponTypeEntity);
        private readonly string keyCount = string.Format("{0}", EntityNameConst.MarketingCouponCountEntity);
        private readonly string keyReceive = string.Format("{0}", EntityNameConst.MarketingCouponReceiveEntity);
        private readonly string keyUsing = string.Format("{0}", EntityNameConst.MarketingCouponUsingEntity);
        public MarketingCouponService(IDatabaseContext databaseContext,
            IMarketingCouponData marketingCouponData,
            IMarketingCouponTypeData marketingCouponTypeData,
            IRedisService redisService,
            IAgentAreaRecordService agentAreaRecordService,
            IZoneService zoneService,
            IMarketingCouponReceiveData marketingCouponReceiveData,
            IMarketingCouponUsingData marketingCouponUsingData,
            IOrderData orderData)
        {
            this.databaseContext = databaseContext;
            this.marketingCouponData = marketingCouponData;
            this.marketingCouponTypeData = marketingCouponTypeData;
            this.redisService = redisService;
            this.agentAreaRecordService = agentAreaRecordService;
            this.zoneService = zoneService;
            this.marketingCouponReceiveData = marketingCouponReceiveData;
            this.marketingCouponUsingData = marketingCouponUsingData;
            this.orderData = orderData;
        }

        public MarketingCouponCountDto GetAllCount(AdminDto admin)
        {
            long? agentRecordId = null;
            if (admin.AgentRecord != null)
            {
                agentRecordId = admin.AgentRecord.AgentRecordId;
            }
            string cacheKey = this.redisService.GetKey(keyCount, agentRecordId);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = marketingCouponTypeData.GetAllCount(agentRecordId).Result.As<MarketingCouponCountDto>();
                return result;
            }, TimeSpan.FromDays(1));
            return resultRedis;


        }
        #region 用户端
        public IEnumerable<MarketingCouponTypeDto> GetCanReceiveList(UserDto userInfo, string countyCode)
        {
            if (string.IsNullOrWhiteSpace(countyCode))
            {
                throw new ArgumentException(" 请选择需要执行的行政区域 ");
            }
            var zoneEntity = zoneService.GetFromZoneEntity(countyCode);
            if (zoneEntity == null || zoneEntity.provinceEntity == null || zoneEntity.cityEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("此区域信息不正确!");
            }
            var agentAreaRecordEntity = agentAreaRecordService.GetLastLevelByCode(zoneEntity.countyEntity.CountyCode);
            if (agentAreaRecordEntity == null)
            {
                throw new ArgumentException(" 该地区正在筹划中 ");
            }

            string cacheKey = this.redisService.GetKey(keyCount, agentAreaRecordEntity.AgentRecordId, zoneEntity.countyEntity.CountyCode);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = marketingCouponTypeData.GetCanReceiveList(agentAreaRecordEntity.AgentRecordId, zoneEntity.countyEntity.CountyCode).Result;
                return result.As<IEnumerable<MarketingCouponTypeDto>>();
            }, TimeSpan.FromDays(1));
            return resultRedis;
        }

        public bool ReceiveMarketingCoupon(UserDto userInfo, long marketingCouponTypeId, string countyCode)
        {
            if (string.IsNullOrWhiteSpace(countyCode))
            {
                throw new ArgumentException(" 请选择需要执行的行政区域 ");
            }
            var zoneEntity = zoneService.GetFromZoneEntity(countyCode);
            if (zoneEntity == null || zoneEntity.provinceEntity == null || zoneEntity.cityEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("此区域信息不正确!");
            }
            var agentAreaRecordEntity = agentAreaRecordService.GetLastLevelByCode(zoneEntity.countyEntity.CountyCode);
            if (agentAreaRecordEntity == null)
            {
                throw new ArgumentException(" 该地区正在筹划中 ");
            }
            var marketingCouponTypeEntity = marketingCouponTypeData.GetSingle(marketingCouponTypeId).Result;
            if (marketingCouponTypeEntity == null)
            {
                throw new ArgumentException(" 获取优惠券类型失败 ");
            }
            if (marketingCouponTypeEntity.AgentRecordId != agentAreaRecordEntity.AgentRecordId)
            {
                throw new ArgumentException(" 优惠券所属代理商和区域代理商不一致,不可领取 ");
            }
            if (marketingCouponTypeEntity.RemainCount == 0)
            {
                throw new ArgumentException(" 当前优惠券已领取完,不可领取 ");
            }
            var marketingCouponEntity = new MarketingCouponEntity
            {
                IsReceive = true
            };
            while (marketingCouponEntity.IsReceive)
            {
                marketingCouponEntity = marketingCouponData.GetRemainMarketingCoupon(marketingCouponTypeId, agentAreaRecordEntity.AgentRecordId).Result;
                if (marketingCouponEntity == null)
                {
                    throw new ArgumentException(" 当前优惠券已领取完,不可领取 ");
                }
            }
            this.databaseContext.BeginTransaction();
            marketingCouponEntity.IsReceive = true;
            marketingCouponEntity.ReceivedTime = DateTime.Now;
            marketingCouponEntity.UserId = userInfo.UserId;
            marketingCouponEntity.UserName = userInfo.UserName;
            this.marketingCouponData.UpdateAsync(marketingCouponEntity).GetAwaiter().GetResult();
            var reusltMarketingCouponType = marketingCouponTypeData.Receive(marketingCouponTypeId).GetAwaiter().GetResult();
            if (reusltMarketingCouponType.RemainCount< 0)
            {
                throw new ArgumentException(" 当前优惠券已领取完,不可领取 ");
            }
            var tempMarketingCouponReceiveEntity = marketingCouponReceiveData.GetEntityById(marketingCouponEntity.MarketingCouponId).Result;
            if (tempMarketingCouponReceiveEntity != null)
            {
                throw new ArgumentException(" 当前优惠券已被人领取,不可重复领取 ");
            }
            var receiveEntity = new MarketingCouponReceiveEntity
            {
                UserId = userInfo.UserId,
                UserName = userInfo.UserName,
                MarketingCouponTypeId = marketingCouponTypeEntity.MarketingCouponTypeId,
                CouponType = marketingCouponTypeEntity.CouponType,
                MarketingCouponId = marketingCouponEntity.MarketingCouponId,
                CouponNumber = marketingCouponEntity.CouponNumber,
                CouponName = marketingCouponEntity.CouponName,
                CouponSummark = marketingCouponEntity.CouponSummark,
                AgentRecordId = marketingCouponEntity.AgentRecordId,
                IsCommon = marketingCouponTypeEntity.IsCommon,
                ProvinceCode = zoneEntity.provinceEntity.ProvinceCode,
                CityCode = zoneEntity.cityEntity.CityCode,
                CountyCode = zoneEntity.countyEntity.CountyCode,
                StartDate = marketingCouponEntity.StartDate,
                EndDate = marketingCouponEntity.EndDate,
                CouponAmount = marketingCouponEntity.CouponAmount,
                CreateTime = DateTime.Now,
                IsCommonBusiness = marketingCouponEntity.IsCommonBusiness,
                VehicleTransportBusinessConfigId = marketingCouponEntity.VehicleTransportBusinessConfigId,
                TransportBusiness = marketingCouponEntity.TransportBusiness,
            };
            var result = this.marketingCouponReceiveData.InsertAsync(receiveEntity).GetAwaiter().GetResult();
            if (result == null)
            {
                throw new ArgumentException(" 优惠券领取记录添加失败,优惠券领取失败 ");
            }
            this.databaseContext.Commit();
            this.redisService.DeleteMultipleKey(keyType, false);
            this.redisService.DeleteMultipleKey(key, false);
            this.redisService.DeleteMultipleKey(keyReceive, false);
            return true;
        }

        public IEnumerable<MarketingCouponDto> GetCanUseList(UserDto userInfo, long vehicleTransportBusinessConfigId, string countyCode)
        {
            if (string.IsNullOrWhiteSpace(countyCode))
            {
                throw new ArgumentException(" 请选择需要执行的行政区域 ");
            }
            var zoneEntity = zoneService.GetFromZoneEntity(countyCode);
            if (zoneEntity == null || zoneEntity.provinceEntity == null || zoneEntity.cityEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("此区域信息不正确!");
            }
            var agentAreaRecordEntity = agentAreaRecordService.GetLastLevelByCode(zoneEntity.countyEntity.CountyCode);
            if (agentAreaRecordEntity == null)
            {
                throw new ArgumentException(" 该地区正在筹划中 ");
            }
            string cacheKey = this.redisService.GetKey(key, userInfo.UserId, vehicleTransportBusinessConfigId, zoneEntity.countyEntity.CountyCode);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = marketingCouponData.GetCanUseList(userInfo.UserId, vehicleTransportBusinessConfigId, zoneEntity.countyEntity.CountyCode).Result;
                return result.As<IEnumerable<MarketingCouponDto>>();
            }, TimeSpan.FromDays(1));
            return resultRedis;
        }

        public bool UseMarketingCoupon(UserDto userInfo, long marketingCouponId, string countyCode, long orderId)
        {
            if (string.IsNullOrWhiteSpace(countyCode))
            {
                throw new ArgumentException(" 请选择需要执行的行政区域 ");
            }
            var marketingCouponEntity = this.marketingCouponData.GetSingle(marketingCouponId).Result;
            if (marketingCouponEntity == null)
            {
                throw new ArgumentException(" 获取优惠券信息失败 ");
            }
            if (marketingCouponEntity.IsUse)
            {
                throw new ArgumentException(" 当前优惠券已被使用,不可重复使用 ");
            }
            if (marketingCouponEntity.UserId != userInfo.UserId)
            {
                throw new ArgumentException(" 当前优惠券不属于你,不可使用 ");
            }
            var orderEntity = this.orderData.GetEntity(orderId).Result;
            if (orderEntity == null)
            {
                throw new ArgumentException(" 获取订单信息失败 ");
            }
            var marketingCouponTypeEntity = this.marketingCouponTypeData.GetSingle(marketingCouponEntity.MarketingCouponTypeId).Result;
            if (marketingCouponTypeEntity == null)
            {
                throw new ArgumentException(" 获取优惠券类型信息失败 ");
            }
            var zoneEntity = zoneService.GetFromZoneEntity(countyCode);
            if (zoneEntity == null || zoneEntity.provinceEntity == null || zoneEntity.cityEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("此区域信息不正确!");
            }
            var agentAreaRecordEntity = agentAreaRecordService.GetLastLevelByCode(zoneEntity.countyEntity.CountyCode);
            if (agentAreaRecordEntity == null)
            {
                throw new ArgumentException(" 该地区正在筹划中 ");
            }
            var tempMarketingCouponUsingEntity = marketingCouponUsingData.GetSingleByCouponId(marketingCouponEntity.MarketingCouponId).Result;
            if (tempMarketingCouponUsingEntity != null)
            {
                throw new ArgumentException(" 当前优惠券已被使用,不可重复使用 ");
            }
            this.databaseContext.BeginTransaction();
            var useEntity = new MarketingCouponUsingEntity
            {
                UserId = userInfo.UserId,
                UserName = userInfo.UserName,
                MarketingCouponTypeId = marketingCouponEntity.MarketingCouponTypeId,
                CouponType = marketingCouponEntity.CouponType,
                MarketingCouponId = marketingCouponEntity.MarketingCouponId,
                CouponNumber = marketingCouponEntity.CouponNumber,
                CouponName = marketingCouponEntity.CouponName,
                CouponSummark = marketingCouponEntity.CouponSummark,
                AgentRecordId = marketingCouponEntity.AgentRecordId,
                IsCommon = marketingCouponEntity.IsCommon,
                ProvinceCode = zoneEntity.provinceEntity.ProvinceCode,
                CityCode = zoneEntity.cityEntity.CityCode,
                CountyCode = zoneEntity.countyEntity.CountyCode,
                StartDate = marketingCouponEntity.StartDate,
                EndDate = marketingCouponEntity.EndDate,
                CouponAmount = marketingCouponEntity.CouponAmount,
                CreateTime = DateTime.Now,
                IsCommonBusiness = marketingCouponEntity.IsCommonBusiness,
                VehicleTransportBusinessConfigId = marketingCouponEntity.VehicleTransportBusinessConfigId,
                TransportBusiness = marketingCouponEntity.TransportBusiness,
                OrderId = orderEntity.OrderId,
                OrderNo = orderEntity.OrderNo,
            };
            this.marketingCouponUsingData.InsertAsync(useEntity).GetAwaiter().GetResult();
            marketingCouponTypeEntity.UsingCount += 1;
            marketingCouponTypeEntity.UpdateTime = DateTime.Now;
            this.marketingCouponTypeData.UpdateAsync(marketingCouponTypeEntity).GetAwaiter().GetResult();

            marketingCouponEntity.IsUse = true;
            marketingCouponEntity.UsingTime = DateTime.Now;
            this.marketingCouponData.UpdateAsync(marketingCouponEntity).GetAwaiter().GetResult();
            this.databaseContext.Commit();
            this.redisService.DeleteMultipleKey(key, false);
            this.redisService.DeleteMultipleKey(keyType, false);
            this.redisService.DeleteMultipleKey(keyUsing, false);
            return true;
        }

        #endregion
        public MarketingCouponDto GetSingle(long marketingCouponId)
        {
            string cacheKey = this.redisService.GetKey(key, marketingCouponId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var entity = this.marketingCouponData.GetSingle(marketingCouponId).GetAwaiter().GetResult();
                return entity;
            }, TimeSpan.FromDays(1));
            return result.As<MarketingCouponDto>();
        }

        public PageableList<MarketingCouponDto> Query(long marketingCouponTypeId, bool? isReceive, bool? isUse, int pageIndex, int pageSize)
        {
            string cacheKey = this.redisService.GetKey(key, marketingCouponTypeId, isReceive, isUse, pageIndex, pageSize);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var (list, dataCount) = this.marketingCouponData.Query(marketingCouponTypeId, isReceive, isUse, pageIndex, pageSize).GetAwaiter().GetResult();
                return new PageableList<MarketingCouponDto>
                {
                    Count = dataCount,
                    Items = list.As<IEnumerable<MarketingCouponDto>>(),
                    PageIndex = pageIndex,
                    PageSize = pageSize,
                    ServerTime = DateTime.Now,
                };
            }, TimeSpan.FromDays(1));
            return result;
        }



        public PageableList<MarketingCouponDto> GetMarketingCouponList(long userId, MarketingCouponStatusEnum? marketingCouponStatus,
            int pageIndex, int pageSize)
        {
            string cacheKey = this.redisService.GetKey(key, userId, marketingCouponStatus, pageIndex, pageSize);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var (list, count) = this.marketingCouponData.GetMarketingCouponList(userId, marketingCouponStatus, pageIndex, pageSize).GetAwaiter().GetResult();
                return new PageableList<MarketingCouponDto>()
                {
                    Items = list.As<IEnumerable<MarketingCouponDto>>(),
                    Count = count,
                    PageIndex = pageIndex,
                    PageSize = pageSize,
                    ServerTime = DateTime.Now,
                };
            }, TimeSpan.FromDays(1));
            return result;
        }

        public bool Delete(long userId, long marketingCouponId)
        {
            var entity = this.marketingCouponData.GetSingle(marketingCouponId).Result;
            if (entity == null)
            {
                throw new ArgumentException(" 获取优惠券信息失败 ");
            }
            if (entity.IsReceive == false)
            {
                throw new ArgumentException(" 当前优惠券尚未领取,不可删除 ");
            }
            if (entity.UserId != userId)
            {
                throw new ArgumentException(" 当前优惠券不属于你,不可删除 ");
            }
            if (!(entity.EndDate < DateTime.Now.Date))
            {
                throw new ArgumentException(" 当前优惠券尚未过期,不可删除 ");
            }
            entity.IsDeleted = true;
            var result = this.marketingCouponData.UpdateAsync(entity).GetAwaiter().GetResult();
            this.redisService.DeleteMultipleKey(key, false);
            return result != null;
        }
    }
}
